package com.element.plaf.xerto;

import com.element.plaf.UIDefaultsLookup;

import javax.swing.*;
import javax.swing.plaf.ColorUIResource;
import java.awt.*;


/**
 * XertoUtils
 *
 * @author Created by Jasper Potts (17-Mar-2005)
 */
public class XertoUtils {
	// =================================================================================================================
	// Xerto Color Methods

	private static Color BASE_COLOR;
	private static Color CONTROL_COLOR;
	private static Color LIGHT_CONTROL_COLOR;
	private static Color MID_CONTROL_COLOR;
	private static Color CONTROL_VERY_LIGHT_SHADOW_COLOR;
	private static Color CONTROL_LIGHT_SHADOW_COLOR;
	private static Color CONTROL_MID_SHADOW_COLOR;
	private static Color CONTROL_DARK_SHADOW_COLOR;

	private static Color SELECTION_COLOR;
	private static Color INACTIVE_CAPTION_COLOR;
	private static Color SELECTED_TAB_BACKGROUND_COLOR;
	private static Color TAB_FORGROUND_COLOR;
	private static Color FRAME_ACTIVE_TITLE_TOP_COLOR;
	private static Color FRAME_ACTIVE_TITLE_BOTTOM_COLOR;
	private static Color FRAME_INACTIVE_TITLE_TOP_COLOR;
	private static Color FRAME_INACTIVE_TITLE_BOTTOM_COLOR;

	static {
		updateColors();
	}

	/**
	 * Updates the colors based on the  current UIDefaults
	 */
	public static void updateColors() {
		UIDefaults uiDefaults = UIManager.getDefaults();
		BASE_COLOR = uiDefaults.getColor("activeCaption");
		if (BASE_COLOR == null) {
			BASE_COLOR = new ColorUIResource(0, 0, 128);
		}
		CONTROL_COLOR = uiDefaults.getColor("control");
		if (CONTROL_COLOR == null) {
			CONTROL_COLOR = new ColorUIResource(Color.GRAY);
		}
		INACTIVE_CAPTION_COLOR = uiDefaults.getColor("inactiveCaption");
		if (INACTIVE_CAPTION_COLOR == null) {
			INACTIVE_CAPTION_COLOR = new ColorUIResource(Color.DARK_GRAY);
		}
		LIGHT_CONTROL_COLOR = uiDefaults.getColor("MenuItem.background");
		if (LIGHT_CONTROL_COLOR == null) {
			LIGHT_CONTROL_COLOR = new ColorUIResource(Color.LIGHT_GRAY);
		}
		// get hsb base colors
		float[] oControlHSB = Color.RGBtoHSB(CONTROL_COLOR.getRed(), CONTROL_COLOR.getGreen(),
				CONTROL_COLOR.getBlue(), null);
		float[] oBaseHSB = Color.RGBtoHSB(BASE_COLOR.getRed(), BASE_COLOR.getGreen(), BASE_COLOR.getBlue(), null);
		// calculate colors
		MID_CONTROL_COLOR = Color.getHSBColor(oControlHSB[0], Math.max(oControlHSB[1] - 0.05f, 0),
				(oControlHSB[2] < 0.95f) ? oControlHSB[2] + 0.05f : 0.98f);
		SELECTED_TAB_BACKGROUND_COLOR = Color.getHSBColor(oControlHSB[0], oControlHSB[1],
				(oControlHSB[1] == 0) ? 0.75f : 0.85f);
		TAB_FORGROUND_COLOR = Color.getHSBColor(oControlHSB[0], (oControlHSB[1] > 0.01) ? 0.45f : oControlHSB[0], 0.2f);
		CONTROL_VERY_LIGHT_SHADOW_COLOR = Color.getHSBColor(oControlHSB[0], oControlHSB[1], oControlHSB[2] - 0.02f);
		CONTROL_LIGHT_SHADOW_COLOR = Color.getHSBColor(oControlHSB[0], oControlHSB[1], oControlHSB[2] - 0.06f);
		CONTROL_MID_SHADOW_COLOR = Color.getHSBColor(oControlHSB[0], oControlHSB[1], oControlHSB[2] - 0.16f);
		CONTROL_DARK_SHADOW_COLOR = Color.getHSBColor(oControlHSB[0], oControlHSB[1], oControlHSB[2] - 0.32f);
		SELECTION_COLOR = Color.getHSBColor(oBaseHSB[0], (oBaseHSB[1] > 0.01) ? 0.45f : oBaseHSB[0], 0.80f);
		FRAME_ACTIVE_TITLE_TOP_COLOR = Color.getHSBColor(oBaseHSB[0], (oBaseHSB[1] > 0.01) ? 0.3f : oBaseHSB[0], 0.90f);
		FRAME_ACTIVE_TITLE_BOTTOM_COLOR = Color.getHSBColor(oBaseHSB[0], (oBaseHSB[1] > 0.01) ? 0.45f : oBaseHSB[0], 0.70f);
		FRAME_INACTIVE_TITLE_TOP_COLOR = Color.getHSBColor(oControlHSB[0], oControlHSB[1], 0.75f);
		FRAME_INACTIVE_TITLE_BOTTOM_COLOR = Color.getHSBColor(oControlHSB[0], oControlHSB[1], 0.5f);
	}

	public static Color getBaseColor() {
		return BASE_COLOR;
	}

	public static Color getInActiveCaptionColor() {
		return INACTIVE_CAPTION_COLOR;
	}

	public static Color getControlColor() {
		return CONTROL_COLOR;
	}

	public static Color getMidControlColor() {
		return MID_CONTROL_COLOR;
	}

	public static Color getLightControlColor() {
		return LIGHT_CONTROL_COLOR;
	}

	public static Color getSelectedTabBackgroundColor() {
		return SELECTED_TAB_BACKGROUND_COLOR;
	}

	public static Color getTabForgroundColor() {
		return TAB_FORGROUND_COLOR;
	}

	public static Color getControlVeryLightShadowColor() {
		return CONTROL_VERY_LIGHT_SHADOW_COLOR;
	}

	public static Color getControlLightShadowColor() {
		return CONTROL_LIGHT_SHADOW_COLOR;
	}

	public static Color getControlMidShadowColor() {
		return CONTROL_MID_SHADOW_COLOR;
	}

	public static Color getControlDarkShadowColor() {
		return CONTROL_DARK_SHADOW_COLOR;
	}

	public static Color getSelectionColor() {
		return SELECTION_COLOR;
	}

	public static Color getApplicationFrameBackgroundColor() {
		return getControlColor();
	}

	public static Color getFrameBorderColor() {
		return UIDefaultsLookup.getColor("controlShadow");
	}

	public static Color getFrameActiveTitleTopColor() {
		return FRAME_ACTIVE_TITLE_TOP_COLOR;
	}

	public static Color getFrameActiveTitleBottomColor() {
		return FRAME_ACTIVE_TITLE_BOTTOM_COLOR;
	}

	public static Color getFrameInactiveTitleTopColor() {
		return FRAME_INACTIVE_TITLE_TOP_COLOR;
	}

	public static Color getFrameInactiveTitleBottomColor() {
		return FRAME_INACTIVE_TITLE_BOTTOM_COLOR;
	}

	// =================================================================================================================
	// Jide Color Methods

	public static Color getLighterColor(Color backColor) {
		int r = getLighterColor(backColor.getRed());
		int g = getLighterColor(backColor.getGreen());
		int b = getLighterColor(backColor.getBlue());
		if (r >= 255) r = 255;
		if (g >= 255) g = 255;
		if (b >= 255) b = 255;
		return new Color(r, g, b);
	}

	public static int getLighterColor(int x) {
		return (int) (x * 36.0 / 255.0 + 219.5);
	}


	public static Color getMenuSelectionColor(Color backColor) {
		int r = getMenuSelectionValue(backColor.getRed());
		int g = getMenuSelectionValue(backColor.getGreen());
		int b = getMenuSelectionValue(backColor.getBlue());
		if (r >= 255) r = 255;
		if (g >= 255) g = 255;
		if (b >= 255) b = 255;
		return new Color(r, g, b);
	}

	public static int getMenuSelectionValue(int x) {
		return (int) (x * 76.0 / 255.0 + 179.5);
	}

	public static Color getMenuBackgroundColor(Color color) {
		if (Color.BLACK.equals(color)) {
			return color;
		} else if (Color.WHITE.equals(color)) {
			return color;
		}
		int r = getMenuValue(color.getRed());
		int g = getMenuValue(color.getGreen());
		int b = getMenuValue(color.getBlue());
		if (r >= 255) r = 255;
		if (g >= 255) g = 255;
		if (b >= 255) b = 255;
		return new Color(r, g, b);
	}

	public static int getMenuValue(int x) {
		return (int) (x * 36.0 / 255.0 + 219.5);
	}

	public static Color getToolBarBackgroundColor(Color color) {
		if (Color.BLACK.equals(color)) {
			return color;
		} else if (Color.WHITE.equals(color)) {
			return color;
		}
		int r = getToolBarValue(color.getRed());
		int g = getToolBarValue(color.getGreen());
		int b = getToolBarValue(color.getBlue());
		if (r >= 255) r = 255;
		if (g >= 255) g = 255;
		if (b >= 255) b = 255;
		return new Color(r, g, b);
	}

	public static int getToolBarValue(int x) {
		return x * 215 / 255 + 40;
	}

	public static Color getGripperForegroundColor(Color backColor) {
		int r = getGripperValue(backColor.getRed());
		int g = getGripperValue(backColor.getGreen());
		int b = getGripperValue(backColor.getBlue());
		if (r >= 255) r = 255;
		if (g >= 255) g = 255;
		if (b >= 255) b = 255;
		return new Color(r, g, b);
	}

	public static int getGripperValue(int x) {
		if (x == 255) {
			return 0;
		} else if (x >= 0 && x <= 64) {
			return x * 33 / 64 + 123;
		} else {
			return (x - 65) * 157 / 189 + 33;
		}
	}

	public static Color getDefaultBackgroundColor(Color backColor) {
		Color backIDE;

		// Check for the 'Classic' control color
		if ((backColor.getRed() == 212) && (backColor.getGreen() == 208) && (backColor.getBlue() == 200)) {
			// Use the exact background for this color
			backIDE = new Color(247, 243, 233);
		} else if ((backColor.getRed() == 236) && (backColor.getGreen() == 233) && (backColor.getBlue() == 216)) {
			// Check for the 'XP' control color
			// Use the exact background for this color
			backIDE = new Color(255, 251, 233);
		} else {
			// Calculate the IDE background color as only half as dark as the control color
			int r = backColor.getRed() + 35;
			int g = backColor.getGreen() + 35;
			int b = backColor.getBlue() + 35;
			if (r >= 255) r = 255;
			if (g >= 255) g = 255;
			if (b >= 255) b = 255;
			backIDE = new Color(r, g, b);
		}

		return backIDE;
	}

	final public static double RATIO1 = 0.67;
	final public static double RATIO2 = 0.78;
	final public static double RATIO3 = 0.86;

	static final Color DARK_GREEN = new Color(0, 128, 0);
	static final Color DARK_MAGENTA = new Color(128, 0, 128);

	public static int getLightColor(int x, double ratio) {
		return (int) ((255 - x) * ratio + x);
	}

	public static Color getLighterColor(Color color, double ratio) {
		if (DARK_GREEN.equals(color) || DARK_MAGENTA.equals(color)) {
			return color;
		}
		int r = getLightColor(color.getRed(), ratio);
		int g = getLightColor(color.getGreen(), ratio) + 1;
		int b = getLightColor(color.getBlue(), ratio);
		if (r >= 255) r = 255;
		if (g >= 255) g = 255;
		if (b >= 255) b = 255;
		return new Color(r, g, b);
	}

	public static Color getHighlightColor(Color bottomColor) {
		float[] oHSB = new float[3];
		Color.RGBtoHSB(bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), oHSB);
		oHSB[1] -= 0.07f;
		if (oHSB[1] < 0) oHSB[1] = 0f;
		oHSB[2] += 0.04f;
		if (oHSB[2] > 1) oHSB[2] = 1f;
		return Color.getHSBColor(oHSB[0], oHSB[1], oHSB[2]);
	}

	public static Color getEmBaseColor(Color bottomColor) {
		float[] oHSB = new float[3];
		Color.RGBtoHSB(bottomColor.getRed(), bottomColor.getGreen(), bottomColor.getBlue(), oHSB);
		oHSB[1] += 0.1f;
		if (oHSB[1] > 1) oHSB[1] = 1f;
		oHSB[2] -= 0.1f;
		if (oHSB[2] < 0) oHSB[2] = 0f;
		return Color.getHSBColor(oHSB[0], oHSB[1], oHSB[2]);
	}

	public static Color getTextColor(Color backgroundColor) {
		float[] oHSB = new float[3];
		Color.RGBtoHSB(backgroundColor.getRed(), backgroundColor.getGreen(), backgroundColor.getBlue(), oHSB);
		return (oHSB[2] > 0.53) ? UIDefaultsLookup.getColor("controlText") : Color.WHITE;
	}

	public static Color getSelectedAndFocusedButtonColor(Color backColor) {
		return getLighterColor(backColor, RATIO1);
	}

	public static Color getFocusedButtonColor(Color backColor) {
		return getLighterColor(backColor, RATIO2);
	}

	public static Color getSelectedButtonColor(Color backColor) {
		return getLighterColor(backColor, RATIO3);
	}
}
